package main

import "fmt"

/*
	1.返回值类型放在函数声明的最后
	2.只有一个返回值并且没有命名返回值的时候,返回值类型可以不用括号括起来
*/
func method1() int {
	return 1
}

/*
	多个返回值的时候必须用括号括起来返回值
*/
func method2() (int, string) {
	return 1, ""
}

/*
	1.可以使用声明式返回值
	2.已经声明的返回值在使用的时候不需要声明，直接使用
*/
func method3() (t int) {
	t = 2
	return
}

/*
	参数可以合并定义类型
*/
func method4(a, b, c, d int) {

}

/*
	1.defer 修饰的表达式最后执行，类似Java的finally代码块
	2.defer 类似栈结构，后进先出
	3.defer Go的return不是原子的，分为两步1.给返回值赋值；2.真正的返回，defer执行在两个步骤中间
*/
func method5() {
	fmt.Println("第一步")
	defer fmt.Println("结束1")
	defer fmt.Println("结束2")
	fmt.Println("第二步")
}

/*
	defer 可以修饰匿名函数
*/
func method6() {
	fmt.Println("第一步")
	defer func() {
		fmt.Println("结束1")
		fmt.Println("结束2")
	}()
	fmt.Println("第二步")
}

/*
	method7和method8是解释defer执行时机的例子
*/
func method7() int {
	x := 5
	defer func() { x++ }()
	return x
}
func method8() (x int) {
	defer func() { x++ }()
	return 5
}

func method9(m func() int) func(int) int {
	return func(arg int) int {
		return arg + m()
	}
}

func main() {
	fmt.Print(method1())
	fmt.Print(method2())
	fmt.Print(method3())
	method5()
	method6()
	println(method7())
	println(method8())
	println(method9(method8)(5))
}
